define(function (require, exports, module) {
    var Utils = require('common-utils');
    require('jquery.form');

    if (typeof(window.globalErrorClass) == 'undefined') {
        window.globalErrorClass = "erro";
    }

    if (typeof(window.globalSuccessClass) == 'undefined') {
        window.globalSuccessClass = "onSuccess";
    }

    if (typeof(window.globalInputErrorClass) == 'undefined') {
        window.globalInputErrorClass = "border_h";
    }

    window.jQuery_formValidator_initConfig = null;

    var regexEnum = {
        intege: "^-?[1-9]\\d*$",					// 整数
        intege1: "^[1-9]\\d*$",					// 正整数
        intege2: "^-[1-9]\\d*$",					// 负整数
        num: "^([+-]?)\\d*\\.?\\d+$",			// 数字
        num1: "^[1-9]\\d*|0$",					// 正数（正整数 + 0）
        num2: "^-[1-9]\\d*|0$",					// 负数（负整数 + 0）
        decmal: "^([+-]?)\\d*\\.\\d+$",			// 浮点数
        decmal1: "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$",	// 正浮点数
        decmal2: "^-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*)$", // 负浮点数
        decmal3: "^-?([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0)$", // 浮点数
        decmal4: "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0$", // 非负浮点数（正浮点数 + 0）
        decmal5: "^(-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*))|0?.0+|0$",// 非正浮点数（负浮点数 + 0）

        email: "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$", // 邮件
        color: "^[a-fA-F0-9]{6}$",				// 颜色
        url: "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$",	// url
        chinese: "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$",					// 仅中文
        ascii: "^[\\x00-\\xFF]+$",				// 仅ACSII字符
        zipcode: "^\\d{6}$",						// 邮编
		mobile: "^(13|14|15|18|17|16|19)[0-9]{9}$",				// 手机        ip4: "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$",	// ip地址
        notempty: "^\\S+$",						// 非空
        picture: "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$",	// 图片
        rar: "(.*)\\.(rar|zip|7zip|tgz)$",								// 压缩文件
        date: "^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$",					// 日期
        qq: "^[1-9]*[1-9][0-9]*$",				// QQ号码
        tel: "^(([0\\+]\\d{2,3}-)?(0\\d{2,3})-)?(\\d{7,8})(-(\\d{3,}))?$",	// 电话号码的函数(包括验证国内区号,国际区号,分机号)
        username: "^\\w+$",						// 用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
        letter: "^[A-Za-z]+$",					// 字母
        letter_u: "^[A-Z]+$",					// 大写字母
        letter_l: "^[a-z]+$",					// 小写字母
        idcard: "^[1-9]([0-9]{14}|[0-9]{17})$"	// 身份证
    };

    function onInputStyle(id, type) {
        if (id != null && id != "") {
            if (id.indexOf("tip_") == -1) {
                var obj = $("#" + id);
                obj.removeClass("onShowInputStyle").removeClass("onFocusInputStyle").removeClass(window.globalInputErrorClass);
                obj.addClass(window.globalInputErrorClass);
            } else {
                var inputId = id.replace("tip_", "");
                var obj = $("#" + inputId);
                obj.removeClass("onShowInputStyle").removeClass("onFocusInputStyle").removeClass(window.globalInputErrorClass);
                obj.addClass(window.globalInputErrorClass);
            }
        }
    }

    function delInputStyle(id) {
        if (id != null && id != "") {
            if (id.indexOf("tip_") == -1) {
                var obj = $("#" + id);
                obj.removeClass("onShowInputStyle");
                obj.removeClass("onFocusInputStyle");
                obj.removeClass(window.globalInputErrorClass);
            } else {
                var inputId = id.replace("tip_", "");
                var obj = $("#" + inputId);
                obj.removeClass("onShowInputStyle");
                obj.removeClass("onFocusInputStyle");
                obj.removeClass(window.globalInputErrorClass);
            }
        }
    }

    function doPreCheck(formId) {
        var form = $('#' + formId);
        var url = form.attr('action') + '?precheckflag=1';
        var data = ajaxSubmitForm(form, url);
        if (data == null) {
            return true;
        }
        if (data.tourl != '') {
            data = ajaxSubmitForm(form, Utils.getContextPath() + data.tourl);
        }
        var success = data.successflg == 0;
        if (!success) {
            alert('[' + data.errorcode + ']' + data.errormsg);
        } else {
            try {
                var noticetype = data.noticetype;	//通知方式，0为空alert框（默认），1为confirm框
                if (noticetype == '1') {
                    return confirm(data.errormsg);
                }
            } catch (e) {
            }
        }
        return success;
    }

    function ajaxSubmitForm(form, url) {
        var jsonObj = null;
        $(form).ajaxSubmit({
            global: false,
            url: url,
            async: true, // notice!!
            dataType: 'json',
            success: function (data, status) {
                jsonObj = data;
            }
        });
        return jsonObj;
    }

    (function ($) {
        $.formValidator = {
            // 各种校验方式支持的控件类型
            sustainType: function (id, setting) {
                var elem = $("#" + id).get(0);
                var srcTag = elem.tagName;
                var stype = elem.type;
                switch (setting.validatetype) {
                    case "InitValidator":
                        return true;
                    case "InputValidator":
                        if (srcTag == "INPUT" || srcTag == "TEXTAREA" || srcTag == "SELECT") {
                            return true;
                        } else {
                            return false;
                        }
                    case "CompareValidator":
                        if (srcTag == "INPUT" || srcTag == "TEXTAREA") {
                            if (stype == "checkbox" || stype == "radio") {
                                return false;
                            } else {
                                return true;
                            }
                        }
                        return false;
                    case "AjaxValidator":
                        if (stype == "text" || stype == "textarea" || stype == "file" || stype == "select-one" || stype == "password") {
                            return true;
                        } else {
                            return false;
                        }
                    case "RegexValidator":
                        if (srcTag == "INPUT" || srcTag == "TEXTAREA") {
                            if (stype == "checkbox" || stype == "radio") {
                                return false;
                            } else {
                                return true;
                            }
                        }
                        return false;
                    case "FunctionValidator":
                        return true;
                }
            },

            initConfig: function (controlOptions) {
                var settings = {
                    debug: false,
                    validatorgroup: "1",
                    showtip: false,
                    alertmessage: false,
                    validobjectids: "",
                    doprecheck: false,
                    onsuccess: function () {
                        return true;
                    },
                    onerror: function () {
                    },
                    submitonce: false,
                    formid: ""
                };
                controlOptions = controlOptions || {};
                $.extend(settings, controlOptions);
                if (settings.formid != "") {
                    $("#" + settings.formid).submit(function () {
                        // 注释掉下面的语句，一个页面两个表单可以通过分组分别校验
                        var result = $.formValidator.pageIsValid(settings);
                        if (result === false) {
                            return false;
                        }
                    });
                }
                if (jQuery_formValidator_initConfig == null) {
                    jQuery_formValidator_initConfig = new Array();
                }
                jQuery_formValidator_initConfig.push(settings);
            },

            // 如果validator对象对应的element对象的validator属性追加要进行的校验。
            appendValid: function (id, setting) {
                // 如果是各种校验不支持的类型，就不追加到。返回-1表示没有追加成功
                if (!$.formValidator.sustainType(id, setting))
                    return -1;
                var srcjo = $("#" + id).get(0);
                if (setting.validatetype == "InitValidator" || !srcjo.settings || srcjo.settings == undefined) {
                    srcjo.settings = new Array();
                }
                var len = srcjo.settings.push(setting);
                srcjo.settings[len - 1].index = len - 1;
                return len - 1;
            },
            deleteValid: function (id) {
                var srcjo = $("#" + id).get(0);
                var settings = srcjo.settings;//删除增加,
                var len = settings.length;
                var settarry = new Array();
                for (var i = 0; i < len; i++) {
                    if (settings[i].appled) {
                        continue;
                    } else {
                        settarry.push(settings[i]);
                    }
                }
                srcjo.settings = settarry;
            },

            // 如果validator对象对应的element对象的validator属性追加要进行的校验。
            getInitConfig: function (validatorgroup) {
                if (jQuery_formValidator_initConfig != null) {
                    for (var i = 0; i < jQuery_formValidator_initConfig.length; i++) {
                        if (validatorgroup == jQuery_formValidator_initConfig[i].validatorgroup) {
                            return jQuery_formValidator_initConfig[i];
                        }
                    }
                }
                return null;
            },

            // 触发每个控件上的各种校验
            triggerValidate: function (returnObj) {
                switch (returnObj.setting.validatetype) {
                    case "InputValidator":
                        $.formValidator.inputValid(returnObj);
                        break;
                    case "CompareValidator":
                        $.formValidator.compareValid(returnObj);
                        break;
                    case "AjaxValidator":
                        $.formValidator.ajaxValid(returnObj);
                        break;
                    case "RegexValidator":
                        $.formValidator.regexValid(returnObj);
                        break;
                    case "FunctionValidator":
                        $.formValidator.functionValid(returnObj);
                        break;
                }
            },

            // 设置显示信息
            setTipState: function (tipid, showclass, showmsg) {
                var tip = $("#" + tipid);
                if (showmsg == null || showmsg == "") {
                    tip.hide();
                    delInputStyle(tipid);
                } else {
                    tip.attr({
                        "style": "display:"
                    });
                    tip.removeClass();
                    tip.addClass(showclass);
                    onInputStyle(tipid, showclass);
                    tip.html(showmsg);
                    // tip.html( "<nobr>"+showmsg+"</nobr>" );
                }
            },

            // 设置错误的显示信息
            setFailState: function (tipid, showmsg) {
                var tip = $("#" + tipid);
                tip.attr({
                    "style": "display:"
                });
                tip.removeClass();
                tip.addClass(window.globalErrorClass);
                tip.html(showmsg);
            },

            // 给输入框增加样式
            appendCtrlClass: function (ctrlid, ctrlclass) {
                var ctrl = $("#" + ctrlid);
                // var cls = ctrl.attr("class");
                var type = ctrl.attr("type");
                if (type != "text" && type != "password") {
                    return;
                }

                if (ctrl.hasClass("i_r")) {
                    ctrl.removeClass("i_r");
                } else if (ctrl.hasClass("i_w")) {
                    ctrl.removeClass("i_w");
                }

                ctrl.addClass(' ' + ctrlclass);
            },

            // 根据单个对象,正确:正确提示,错误:错误提示
            showMessage: function (returnObj) {
                var id = returnObj.id;
                var isvalid = returnObj.isvalid;
                var setting = returnObj.setting;// 正确:setting[0],错误:对应的setting[i]
                var showmsg = "";
                var showclass = "";
                var settings = $("#" + id).get(0).settings;
                var intiConfig = $.formValidator.getInitConfig(settings[0].validatorgroup);
                if (!isvalid) {
                    if (setting.validatetype == "AjaxValidator") {
                        if (setting.lastValid == "" || setting.lastValid == "-1") {
                            showclass = "onLoad";
                            showmsg = setting.onwait;
                        } else if (setting.lastValid == "0") {
                            showclass = window.globalErrorClass;
                            showmsg = setting.lastMsg;
                        }
                    } else {
                        showmsg = (returnObj.errormsg == "" ? setting.onerror : returnObj.errormsg);
                        showclass = window.globalErrorClass;
                    }
                    if (intiConfig.alertmessage) {
                        var elem = $("#" + id).get(0);
                        if (elem.validoldvalue != $(elem).val()) {
                            alert(showmsg);
                        }
                    } else {
                        $.formValidator.setTipState(settings[0].tipid, showclass, showmsg);
                        // 20090428 失败，修改显示样式
                        if (showclass == window.globalErrorClass) {
                            $.formValidator.appendCtrlClass(id, "i_w");
                        }
                        // end of 20090428
                    }

                } else {
                    // 验证成功后,如果没有设置成功提示信息,则给出默认提示,否则给出自定义提示;允许为空,值为空的提示
                    if (!intiConfig.alertmessage) {
                        var showmsg = "";
                        if ($.formValidator.isEmpty(id)) {
                            showmsg = setting.onempty;
                        } else {
                            showmsg = setting.oncorrect;
                        }
                        $.formValidator.setTipState(setting.tipid, window.globalSuccessClass, showmsg);
                        // 20090428
                        $.formValidator.appendCtrlClass(id, "i_r");
                        // end of 20090428
                    }
                }
            },

            // 获取指定字符串的长度
            getLength: function (id) {
                var srcjo = $("#" + id);
                sType = srcjo.get(0).type;
                var len = 0;
                switch (sType) {
                    case "text":
                    case "hidden":
                    case "password":
                    case "textarea":
                    case "file":
                        var val = srcjo.val();
                        for (var i = 0; i < val.length; i++) {
                            if (val.charCodeAt(i) >= 0x4e00 && val.charCodeAt(i) <= 0x9fa5) {
                                len += 2;
                            } else {
                                len++;
                            }
                        }
                        break;
                    case "checkbox":
                    case "radio":
                        len = $("input[type='" + sType + "'][name='" + srcjo.attr("name") + "']:checked").length;
                        break;
                    case "select-one":
                        len = srcjo.get(0).options ? srcjo.get(0).options.selectedIndex : -1;
                        break;
                    case "select-multiple":
                        len = $("select[name=" + srcjo.get(0).name + "] option:selected").length;
                        break;
                }
                return len;
            },

            // 结合empty这个属性，判断仅仅是否为空的校验情况。
            isEmpty: function (id) {
                if ($("#" + id).get(0).settings[0].empty && $.formValidator.getLength(id) == 0) {
                    return true;
                } else {
                    return false;
                }
            },

            // 对外调用：判断单个表单元素是否验证通过，不带回调函数
            isOneValid: function (id) {
                return $.formValidator.oneIsValid(id, 1).isvalid;
            },

            // 去除控件前后的空格 20090218
            trimCtrlVal: function (id) {
                var srcjo = $("#" + id);
                sType = srcjo.get(0).type;

                switch (sType) {
                    case "text":
                    case "textarea":
                        if (srcjo) {
                            srcjo.val(srcjo.val().replace(/(^\s*)|(\s*$)/g, ""));
                        }
                        break;
                }
            },

            // 验证单个是否验证通过,正确返回settings[0],错误返回对应的settings[i]
            oneIsValid: function (id, index) {
                $.formValidator.trimCtrlVal(id);

                var returnObj = new Object();
                returnObj.id = id;
                returnObj.ajax = -1;
                returnObj.errormsg = ""; // 自定义错误信息
                var ctrlObj = $("#" + id);
                var elem = ctrlObj.get(0);
                var settings = elem.settings;
                var settingslen = settings.length;
                // zcb 20090821 start，是否必填，由元素的required属性决定

                var sRequired = ctrlObj.attr("required");
                var sRequiredMsg = ctrlObj.attr("requiredMsg");
                // alert(sRequired + "," + sRequiredMsg);

                if (sRequired == true || sRequired == "true") {
                    var setting_temp = {
                        isvalid: false,
                        min: 1,
                        max: 99999999999999,
                        type: "size",
                        onerror: sRequiredMsg,
                        validatetype: "InputValidator",
                        empty: {
                            leftempty: false,
                            rightempty: false,
                            emptyerror: sRequiredMsg
                        }
                    };

                    var tmpSettings = new Array(settingslen + 1);
                    tmpSettings[0] = settings[0];
                    tmpSettings[1] = setting_temp;
                    for (var i = 1; i < settingslen; i++) {
                        tmpSettings[i + 1] = settings[i];
                    }
                    settings = tmpSettings;
                    settingslen = settings.length;
                }
                // zcb 20090821 end

                // 只有一个formValidator的时候不检验
                if (settingslen == 1) {
                    settings[0].bind = false;
                }
                if (!settings[0].bind) {
                    return null;
                }
                for (var i = 0; i < settingslen; i++) {
                    if (i == 0) {
                        if ($.formValidator.isEmpty(id)) {
                            returnObj.isvalid = true;
                            returnObj.setting = settings[0];
                            break;
                        }
                        continue;
                    }
                    returnObj.setting = settings[i];
                    if (settings[i].validatetype != "AjaxValidator") {
                        $.formValidator.triggerValidate(returnObj);
                    } else {
                        returnObj.ajax = i;
                    }
                    if (!settings[i].isvalid) {
                        returnObj.isvalid = false;
                        returnObj.setting = settings[i];
                        break;
                    } else {
                        returnObj.isvalid = true;
                        returnObj.setting = settings[0];
                        if (settings[i].validatetype == "AjaxValidator")
                            break;
                    }
                }
                $.formValidator.showMessage(returnObj);
                return returnObj;
            },

            resetTipState: function (validatorgroup) {
                var initConfig = $.formValidator.getInitConfig(validatorgroup);
                var jqObjs = $(initConfig.validobjectids);
                jqObjs.each(function () {
                    var setting0 = this.settings[0];
                    $.formValidator.setTipState(setting0.tipid, "onShow", setting0.onshow);
                });
            },

            // 验证所有需要验证的对象，并返回是否验证成功。
            pageIsValid: function (settings) {
                if (typeof (settings) == 'string' || typeof (settings) == 'number') {
                    settings = $.formValidator.getInitConfig(settings);
                }
                var validatorgroup = "1";
                if (settings != undefined)
                    validatorgroup = settings.validatorgroup;
                var isvalid = true;
                var thefirstid = "", thefirsterrmsg = "";
                var returnObj;
                var error_tip = "^";
                var initConfig = $.formValidator.getInitConfig(validatorgroup);
                var jqObjs = $(initConfig.validobjectids);
                // added by zcb 20081210 如果是不存在配置，则直接返回成功
                if (!jqObjs) {
                    return true;
                }

                // 只有1个元素未校验通过才不聚焦
                var count = 0;
                // 20090519 added by zcb
                var errormsgs = "";
                var errormsg = "";
                var array1 = new Array();
                j = 0;
                // end
                jqObjs.each(function (i, elem) {
                    if (elem.settings && elem.settings[0].bind) {
                        returnObj = $.formValidator.oneIsValid(elem.id, 1);
                        // alert("returnObj..." + elem.id + "," +
                        // returnObj.isvalid);
                        if (elem.type == "radio") {
                            for (var k = 0; k < array1.length; k++) {
                                if (array1[k] == elem.name)
                                    return;
                            }
                            array1.push(elem.name);
                        }
                        if (returnObj) {
                            var tipid = elem.settings[0].tipid;
                            // 校验失败,获取第一个发生错误的信息和ID
                            if (!returnObj.isvalid) {
                                count++; // 累计错误计数
                                isvalid = false;

                                errormsg = (returnObj.errormsg == "" ? returnObj.setting.onerror : returnObj.errormsg);
                                errormsgs += errormsg;
                                errormsgs += "\n";
                                // alert("errmsg="+errormsgs);
                                if (thefirstid == "") {
                                    thefirstid = returnObj.id;
                                    thefirsterrmsg = errormsg;

                                }
                            }
                            // 为了解决使用同个TIP提示问题:后面的成功或失败都不覆盖前面的失败
                            if (!initConfig.alertmessage) {
                                if (error_tip.indexOf("^" + tipid + "^") == -1) {
                                    error_tip = error_tip + tipid + "^";
                                    if (!returnObj.isvalid) {
                                        error_tip = error_tip + tipid + "^";
                                    }
                                    $.formValidator.showMessage(returnObj);
                                }
                            }
                        }
                    }
                });
                // added by gavin 20120604
                if (isvalid && settings != undefined && settings.doprecheck && settings.formid.length > 0) {
                    isvalid = doPreCheck(settings.formid);
                }

                // 成功或失败后，进行回调函数的处理，以及成功后的灰掉提交按钮的功能
                if (isvalid) {
                    isvalid = initConfig.onsuccess();
                    // if(initConfig.submitonce){$("input[type='submit']").attr("disabled",true);}
                    // modified by zcb 20090104

                    // commented by hyc
                    /*if (initConfig.submitonce) {
                        // 暂时采用
                        var btnSubmitCtrl = $("button[type=submit]");
                        var inputSubmitCtrl = $("input[type=submit]");

                        if (btnSubmitCtrl.length > 0) {
                            btnSubmitCtrl.attr("disabled", "disabled");
                        } else {
                            inputSubmitCtrl.attr("disabled", "disabled");
                        }
                    } else { // 对于一个页面有多个表单的情况，用这种方式
                        var submitId = initConfig.formid + "_submit";
                        var submitCtrl = $("#" + submitId);
                        if (submitCtrl.length > 0) {
                            submitCtrl.attr("disabled", "disabled");
                        }
                    }*/
                } else {
                    if (thefirstid != '') {
                        var obj = $("#" + thefirstid).get(0);
                        // initConfig.onerror(thefirsterrmsg,obj);
                        // 20090519 如果是弹出窗口校验，则输入所有表单失败的错误信息，否则只输出当前的错误信息
                        if (!initConfig.alertmessage) {
                            initConfig.onerror(thefirsterrmsg, obj);
                        } else {
                            initConfig.onerror(errormsgs, obj);
                        }
                        // 20090519 zcb 如果是几个校验不通过都聚焦
                        // if(count>1){//只有1个元素未校验通过才不聚焦
                        if($("#" + thefirstid).attr("type") != "password") {  // 解决IE7、8下，自动对焦无法触发placeholder事件,导致软keyboard因为input不可见，导致偏移
                            $("#" + thefirstid).focus();
                        }
                    }
                }
                return !initConfig.debug && isvalid;
            },

            // 验证所有需要验证的对象，并返回是否验证成功。
            pageIsValidAndDoError: function (validatorgroup) {
                if (validatorgroup == null || validatorgroup == undefined)
                    validatorgroup = "1";
                var isvalid = true;
                var thefirstid = "", thefirsterrmsg = "";
                var returnObj;
                var error_tip = "^";
                var initConfig = $.formValidator.getInitConfig(validatorgroup);
                var jqObjs = $(initConfig.validobjectids);
                // added by zcb 20081210 如果是不存在配置，则直接返回成功
                if (jqObjs.length == 0) {
                    return true;
                }

                // 只有1个元素未校验通过才不聚焦
                var count = 0;
                // 20090519 added by zcb
                var errormsgs = "";
                var errormsg = "";
                var array1 = new Array();
                j = 0;
                // end
                jqObjs.each(function (i, elem) {
                    if (elem.settings[0].bind) {
                        returnObj = $.formValidator.oneIsValid(elem.id, 1);
                        // alert("returnObj..." + elem.id + "," +
                        // returnObj.isvalid);
                        if (elem.type == "radio") {
                            for (var k = 0; k < array1.length; k++) {
                                if (array1[k] == elem.name)
                                    return;
                            }
                            array1.push(elem.name);
                        }
                        if (returnObj) {
                            var tipid = elem.settings[0].tipid;
                            // 校验失败,获取第一个发生错误的信息和ID
                            if (!returnObj.isvalid) {
                                count++; // 累计错误计数
                                isvalid = false;

                                errormsg = (returnObj.errormsg == "" ? returnObj.setting.onerror : returnObj.errormsg);
                                errormsgs += errormsg;
                                errormsgs += "\n";
                                // alert("errmsg="+errormsgs);
                                if (thefirstid == "") {
                                    thefirstid = returnObj.id;
                                    thefirsterrmsg = errormsg;

                                }
                            }
                            // 为了解决使用同个TIP提示问题:后面的成功或失败都不覆盖前面的失败
                            if (!initConfig.alertmessage) {
                                if (error_tip.indexOf("^" + tipid + "^") == -1) {
                                    error_tip = error_tip + tipid + "^";
                                    if (!returnObj.isvalid) {
                                        error_tip = error_tip + tipid + "^";
                                    }
                                    $.formValidator.showMessage(returnObj);
                                }
                            }
                        }
                    }
                });
                // 指处理失败后进行回调函数
                if (!isvalid) {
                    var obj = $("#" + thefirstid).get(0);
                    // initConfig.onerror(thefirsterrmsg,obj);
                    // 20090519 如果是弹出窗口校验，则输入所有表单失败的错误信息，否则只输出当前的错误信息
                    if (!initConfig.alertmessage) {
                        initConfig.onerror(thefirsterrmsg, obj);
                    } else {
                        initConfig.onerror(errormsgs, obj);
                    }
                    // 20090519 zcb 如果是几个校验不通过都聚焦
                    // if(count>1){//只有1个元素未校验通过才不聚焦
                    if (thefirstid != "") {
                        $("#" + thefirstid).focus();
                    }
                    // }
                } else {
                    // modify by litg 2013-04-15
                    if (typeof (doAfterValidate) != "undefined" && jQuery.isFunction(doAfterValidate)) {
                        doAfterValidate();
                    }
                }
                return !initConfig.debug && isvalid;
            },

            // ajax校验
            ajaxValid: function (returnObj) {
                var id = returnObj.id;
                var srcjo = $("#" + id);
                var setting = srcjo.get(0).settings[returnObj.ajax];
                var ls_url = setting.url;
                if (srcjo.size() == 0 && srcjo.get(0).settings[0].empty) {
                    returnObj.setting = $("#" + id).get(0).settings[0];
                    returnObj.isvalid = true;
                    $.formValidator.showMessage(returnObj);
                    setting.isvalid = true;
                    return;
                }

                var setting0 = srcjo.get(0).settings[0];
                var intiConfig = $.formValidator.getInitConfig(setting0.validatorgroup);

                if (setting.addidvalue) {
                    var parm = "clientid=" + id + "&" + id + "=" + encodeURIComponent(srcjo.val()) + '&r='+new Date().getTime();
                    ls_url = ls_url + ((ls_url).indexOf("?") > 0 ? ("&" + parm) : ("?" + parm));
                }

                ls_url = Utils.generUrl(ls_url);
                $.ajax({
                    global: false,
                    mode: "abort",
                    type: setting.type,
                    url: ls_url,
                    cache: setting.cache,
                    data: $.isFunction(setting.data) ? setting.data() : setting.data,
                    async: setting.async== "undefined" ? true:setting.async,
                    dataType: setting.datatype,
                    success: function (data) {
                        if (!data.success && data.errorcode == 'ETS-5BP00001') { // 登录超时
                            window.top.location = (Utils.getContextPath() + '/timeout');
                            return;
                        }

                        // 在form上面提示错误信息
                        var tip_formid = "tip_" + intiConfig.formid;
                        var tip_formid_obj = $("#" + tip_formid);

                        if (setting.success(data)) {
                            // 20081225 成功，则不显示信息提示div
                            if (tip_formid_obj) {
                                tip_formid_obj.hide();
                            }
                            // end
                            $.formValidator.setTipState(setting0.tipid, window.globalSuccessClass, setting0.oncorrect);
                            // 20090428 提示信息，输入框样式
                            $.formValidator.appendCtrlClass(srcjo.get(0).id, "i_r");
                            // end of 20090428
                            setting.isvalid = true;
                        } else {
                            // $.formValidator.setTipState(setting0.tipid,window.globalErrorClass,setting.onerror);
                            // modified by zcb 20081223
                            // 在form上面提示错误信息
                            // if(tip_formid_obj) {
                            // tip_formid_obj.html(data.errormsg).show();
                            // }
                            // 错误信息用服务端返回的覆盖
                            if (intiConfig.alertmessage) {
                                intiConfig.onerror(data.errormessage);
                            } else {
                                $.formValidator.setTipState(setting0.tipid, window.globalErrorClass, data.errormessage);
                            }
                            // end
                            // 20090428 提示信息，输入框样式
                            $.formValidator.appendCtrlClass(srcjo.get(0).id, "i_w");
                            // end of 20090428
                            $("#loginForm_img_authcode").click();
                            setting.isvalid = false;
                        }
                        setting.lastValid = setting.isvalid ? '1' : '0';
                        setting.lastMsg = data.errormessage;
                    },
                    complete: function () {
                        if (setting.buttons && setting.buttons.length > 0)
                            setting.buttons.removeAttr("disabled");
                        setting.complete;
                    },
                    beforeSend: function (xhr) {
                        // 再服务器没有返回数据之前，先回调提交按钮
                        if (setting.buttons && setting.buttons.length > 0)
                            setting.buttons.attr("disabled", "disabled");
                        var isvalid = setting.beforesend(xhr);
                        if (isvalid)
                            setting.isvalid = false; // 如果前面ajax请求成功了，再次请求之前先当作错误处理
                        setting.lastValid = "-1";
                        return isvalid;
                    },
                    error: function () {
                        if (intiConfig.alertmessage) {
                            intiConfig.onerror(setting.onerror);
                        } else {
                            $.formValidator.setTipState(setting0.tipid, window.globalErrorClass, setting.onerror);
                        }
                        setting.isvalid = false;
                        setting.lastValid = '0';
                        setting.lastMsg = setting.onerror;
                        setting.error();
                    },
                    processData: setting.processdata
                });
            },

            // 对正则表达式进行校验（目前只针对input和textarea）
            regexValid: function (returnObj) {
                var id = returnObj.id;
                var setting = returnObj.setting;
                var elem = $("#" + id).get(0);
                // 如果有输入正则表达式，就进行表达式校验
                if (elem.settings[0].empty && elem.value == "") {
                    setting.isvalid = true;
                } else {
                    var regexpress = setting.regexp;
                    if (setting.datatype == "enum") {
                        regexpress = regexEnum[regexpress];
                    }
                    if (regexpress == undefined || regexpress == "") {
                        setting.isvalid = false;
                        return;
                    }
                    var exp = new RegExp(regexpress, setting.param);
                    if (exp.test($("#" + id).val())) {
                        setting.isvalid = true;
                    } else {
                        setting.isvalid = false;
                    }
                }
            },

            // 函数校验。返回true/false表示校验是否成功;返回字符串表示错误信息，校验失败;如果没有返回值表示处理函数，校验成功
            functionValid: function (returnObj) {
                var id = returnObj.id;
                var setting = returnObj.setting;
                var srcjo = $("#" + id);
                var lb_ret = setting.fun(srcjo.val(), srcjo.get(0));
                if (lb_ret != undefined) {
                    if (typeof lb_ret == "string") {
                        setting.isvalid = false;
                        returnObj.errormsg = lb_ret;
                    } else {
                        setting.isvalid = lb_ret;
                    }
                }
            },

            // 对input和select类型控件进行校验
            inputValid: function (returnObj) {
                var id = returnObj.id;
                var setting = returnObj.setting;
                var srcjo = $("#" + id);
                var elem = srcjo.get(0);
                var val = srcjo.val();
                var sType = elem.type;
                var len = $.formValidator.getLength(id);
                var empty = setting.empty, emptyerror = false;
                switch (sType) {
                    case "text":
                    case "hidden":
                    case "password":
                    case "textarea":
                    case "file":
                        if (setting.type == "size") {
                            empty = setting.empty;
                            if (!empty.leftempty) {
                                emptyerror = (val.replace(/^[ \s]+/, '').length != val.length);
                            }
                            if (!emptyerror && !empty.rightempty) {
                                emptyerror = (val.replace(/[ \s]+$/, '').length != val.length);
                            }
                            if (emptyerror && empty.emptyerror) {
                                returnObj.errormsg = empty.emptyerror;
                            }
                        }
                    case "checkbox":
                    case "select-one":
                    case "select-multiple":
                    case "radio":
                        var li_panduan = false;
                        if (sType == "select-one" || sType == "select-multiple") {
                            setting.type = "size";
                            // added by zcb 20081205 如果下拉框只有一项，则无论选什么都认为校验通过
                            // alert(len + "," + elem.options.length);
                            /* if (1 == elem.options.length) {
                             li_panduan = false;
                             setting.isvalid = true; // 认为校验通过
                             return;
                             }*/
                            if (val && val.length != 0) {
                                // 证件类型，身份证的代码就是0，所以如果是下拉框，则值如果是非空就认为是已选中
                                li_panduan = false;
                                setting.isvalid = true; // 认为校验通过
                                return;
                            }
                            // end
                        }
                        if (setting.type == "size") { // 获得输入的字符长度，并进行校验
                            if (!emptyerror) {
                                li_panduan = true;
                            }
                            if (li_panduan) {
                                val = len;
                            }
                        } else {
                            stype = (typeof setting.min);
                            if (stype == "number") {
                                val = (new Number(val)).valueOf();
                                if (!isNaN(val)) {
                                    li_panduan = true;
                                }
                            }
                            if (stype == "string") {
                                li_panduan = true;
                            }
                        }
                        if (li_panduan) {
                            if (val < setting.min || val > setting.max) {
                                if (val < setting.min && setting.onerrormin) {
                                    returnObj.errormsg = setting.onerrormin;
                                }
                                if (val > setting.min && setting.onerrormax) {
                                    returnObj.errormsg = setting.onerrormax;
                                }
                                setting.isvalid = false;
                            } else {
                                setting.isvalid = true;
                            }
                        } else {
                            setting.isvalid = false;
                        }
                        break;
                }
            },

            compareValid: function (returnObj) {
                var id = returnObj.id;
                var setting = returnObj.setting;
                var srcjo = $("#" + id);
                var desjo = $("#" + setting.desid);
                setting.isvalid = false;
                curvalue = srcjo.val();
                ls_data = desjo.val();
                if (setting.datatype == "number") {
                    if (!isNaN(curvalue) && !isNaN(ls_data)) {
                        curvalue = parseFloat(curvalue);
                        ls_data = parseFloat(ls_data);
                    } else {
                        return;
                    }
                }

                switch (setting.operateor) {
                    case "=":
                        if (curvalue == ls_data) {
                            setting.isvalid = true;
                        }
                        break;
                    case "!=":
                        if (curvalue != ls_data) {
                            setting.isvalid = true;
                        }
                        break;
                    case ">":
                        if (curvalue > ls_data) {
                            setting.isvalid = true;
                        }
                        break;
                    case ">=":
                        if (curvalue >= ls_data) {
                            setting.isvalid = true;
                        }
                        break;
                    case "<":
                        if (curvalue < ls_data) {
                            setting.isvalid = true;
                        }
                        break;
                    case "<=":
                        if (curvalue <= ls_data) {
                            setting.isvalid = true;
                        }
                        break;
                    case "oneok":
                        if ($.formValidator.isEmpty(id)
                            || $.formValidator.isEmpty(isEmpty.desid)) {
                            setting.isvalid = false;
                        } else {
                            setting.isvalid = true;
                        }
                }
            }
        };

        // 每个校验控件必须初始化的
        $.fn.formValidator = function (msgOptions) {
            var setting = {
                validatorgroup: "1",
                empty: false,
                submitonce: false,
                automodify: false,
                onshow: "请输入内容",
                onfocus: "请输入内容",
                oncorrect: "输入正确",
                onempty: "输入内容为空",
                defaultvalue: null,
                bind: true,
                validatetype: "InitValidator",
                tipcss: {
                    "left": "10px",
                    "top": "1px",
                    "height": "20px",
                    "width": "250px"
                },
                triggerevent: "blur"
            };

            // 先合并整个配置(深度拷贝)
            msgOptions = msgOptions || {};
            $.extend(true, setting, msgOptions);

            // 获取该校验组的全局配置信息
            var initConfig = $.formValidator.getInitConfig(setting.validatorgroup);

            return this.each(function () {
                var setting_temp = {};
                $.extend(setting_temp, setting);
                // 自动形成TIP
                var tip = "";
                if (!setting_temp.tipid) {
                    setting_temp.tipid = "tip_" + this.id;
                }
                tip = setting_temp.tipid;

                // 每个控件都要保存这个配置信息
                $.formValidator.appendValid(this.id, setting_temp);

                // 保存控件ID
                var validobjectids = initConfig.validobjectids;
                if (validobjectids.indexOf("#" + this.id + " ") == -1) {
                    initConfig.validobjectids = (validobjectids == "" ? "#" + this.id : validobjectids + ",#" + this.id);
                }
                // 泰达需求，开户银行页面提示银行卡号
                // 如果其它业务的银行页面不需要此提示，在资源中去掉onShow资源即可
                // by zouxu
                var formName = initConfig.validatorgroup;
                var id = this.id;
                if (formName != null && formName != "") {
                    if (formName.indexOf("identifyform") >= 0 && id.indexOf("bankacco") >= 0) {
                        $.formValidator.appendCtrlClass(this.id, "i_msg");
                        $.formValidator.setTipState(tip, "onShow", setting.onshow);
                    }
                }

                // 初始化显示信息
                if (!initConfig.alertmessage) {
                    // 20090428 提示信息，输入框样式
                    $.formValidator.appendCtrlClass(this.id, "i_msg");
                    // end of 20090428
                    $.formValidator.setTipState(tip, "onShow", setting.onshow);
                }

                // 注册事件
                var srcTag = this.tagName;
                var stype = this.type;
                var defaultvalue = setting.defaultvalue;
                var jqobj = $(this);

                if (srcTag == "INPUT" || srcTag == "TEXTAREA") {
                    // 处理默认值
                    if (defaultvalue) {
                        if (stype == "checkbox" || stype == "radio") {
                            if (stype == "radio") {
                                if (this.value == defaultvalue) {
                                    jqobj.attr("checked", true);
                                }
                            } else {
                                jqobj.attr("checked", $.inArray(this.value, defaultvalue) >= 0);
                            }
                        } else {
                            jqobj.val(defaultvalue);
                        }
                    }

                    // 注册获得焦点的事件。改变提示对象的文字和样式，保存原值
                    jqobj.focus(function () {
                        if (!initConfig.alertmessage) {
                            if (null != document.getElementById(tip) && document.getElementById(tip).className != window.globalErrorClass) {
                                $.formValidator.setTipState(tip, "onFocus", setting.onfocus);
                            }
                        }
                        if (stype == "password" || stype == "text" || stype == "textarea" || stype == "file") {
                            this.validoldvalue = jqobj.val();
                        }
                    });
                    // 注册失去焦点的事件。进行校验，改变提示对象的文字和样式；出错就提示处理
                    jqobj.bind(setting.triggerevent, function () {
                        var settings = this.settings;
                        if (initConfig.alertmessage == true && this.type == "radio") {
                            return;
                        }
                        var returnObj = $.formValidator.oneIsValid(this.id, 1);
                        if (returnObj == null) {
                            return;
                        }
                        if (returnObj.ajax >= 0) {
                            if (this.validoldvalue != $(this).val()) {
                                $.formValidator.setTipState(tip, "onLoad", settings[returnObj.ajax].onwait);
                                $.formValidator.ajaxValid(returnObj);
                            } else {
                                $.formValidator.showMessage(returnObj);
                            }
                        } else {
                            $.formValidator.showMessage(returnObj);
                            if (!returnObj.isvalid) {
                                // 自动修正错误
                                var auto = setting.automodify && (this.type == "text" || this.type == "textarea" || this.type == "file");
                                if (auto && !initConfig.alertmessage) {
                                    alert(returnObj.setting.onerror);
                                    $.formValidator.setTipState(tip, "onShow", setting.onshow);
                                }
                            }
                        }
                    });
                } else if (srcTag == "SELECT") {
                    // 设置默认值
                    if (defaultvalue) {
                        if (stype == "select-one") {
                            jqobj.attr("value", defaultvalue);
                        }
                    }
                    // 获得焦点或单击
                    // stype=="select-one"?"focus":"click"
                    jqobj.bind(stype == "select-one" ? "focus" : "click", function () {
                        if (!initConfig.alertmessage) {
                            var tipclass = document.getElementById(tip).className;
                            if (tipclass != window.globalErrorClass && stype != "select-one")
                                $.formValidator.setTipState(tip, "onFocus", setting.onfocus);
                        }
                    });

                    // 选择项目后触发
                    jqobj.bind(stype == "select-one" ? "change" : "blur", function () {
                        var returnObj = $.formValidator.oneIsValid(this.id, 1);
                        if (returnObj == null) {
                            return;
                        }
                        if (returnObj.ajax >= 0 && this.validoldvalue != $(this).val()) {
                            $.formValidator.ajaxValid(this.id, returnObj.setting);
                        } else {
                            $.formValidator.showMessage(returnObj);
                        }
                    });
                }
            });
        };

        $.fn.validateSelf = function () {
            var el = this[0];// jquery to dom object
            // 如果元素为空，则不校验
            if (typeof (el) == "undefined" || el == null || el == "") {
                return;
            }

            var settings = el.settings;
            // 如果元素未配置校验，则不校验
            if (typeof (settings) == "undefined" || settings == null || settings == "") {
                return;
            }

            var validategroup = 1;
            if (typeof (settings) != "undefined" && settings != null && settings.length > 0) {
                validategroup = settings[0].validatorgroup;
            }
            // 获取该校验组的全局配置信息
            var returnObj = $.formValidator.oneIsValid(el.id, validategroup);

            var initConfig = $.formValidator.getInitConfig(validategroup);
            var setting_temp = {};
            $.extend(setting_temp, returnObj.setting);

            // 自动形成TIP
            var tip = "";
            if (!setting_temp.tipid) {
                setting_temp.tipid = "tip_" + el.id;
            }
            tip = setting_temp.tipid;

            if (returnObj == null) {
                return;
            }
            if (returnObj.ajax >= 0) {
                $.formValidator.setTipState(tip, "onLoad", returnObj.setting.onwait);
                $.formValidator.ajaxValid(returnObj);
            } else {
                $.formValidator.showMessage(returnObj);
                if (!returnObj.isvalid) {
                    // 自动修正错误
                    var auto = returnObj.setting.automodify && (el.type == "text" || el.type == "textarea" || el.type == "file");
                    if (auto && !initConfig.alertmessage) {
                        alert(returnObj.setting.onerror);
                        $.formValidator.setTipState(tip, "onShow", returnObj.setting.onshow);
                    } else {
                        this.focus();
                    }
                }
            }
        };

        $.fn.inputValidator = function (controlOptions) {
            var settings = {
                isvalid: false,
                min: 0,
                max: 99999999999999,
                type: "size",
                onerror: "输入错误",
                validatetype: "InputValidator",
                empty: {
                    leftempty: true,
                    rightempty: true,
                    leftemptyerror: null,
                    rightemptyerror: null
                }
            };
            controlOptions = controlOptions || {};
            $.extend(true, settings, controlOptions);
            return this.each(function () {
                $.formValidator.appendValid(this.id, settings);
            });
        };

        $.fn.compareValidator = function (controlOptions) {
            var settings = {
                isvalid: false,
                desid: "",
                operateor: "=",
                onerror: "输入错误",
                validatetype: "CompareValidator"
            };
            controlOptions = controlOptions || {};
            $.extend(true, settings, controlOptions);
            return this.each(function () {
                $.formValidator.appendValid(this.id, settings);
            });
        };

        $.fn.regexValidator = function (controlOptions) {
            var settings = {
                isvalid: false,
                regexp: "",
                param: "i",
                datatype: "string",
                onerror: "输入的格式不正确",
                validatetype: "RegexValidator"
            };
            controlOptions = controlOptions || {};
            $.extend(true, settings, controlOptions);
            return this.each(function () {
                $.formValidator.appendValid(this.id, settings);
            });
        };

        $.fn.functionValidator = function (controlOptions) {
            var settings = {
                isvalid: true,
                fun: function () {
                    this.isvalid = true;
                },
                validatetype: "FunctionValidator",
                onerror: "输入错误"
            };
            controlOptions = controlOptions || {};
            $.extend(true, settings, controlOptions);
            return this.each(function () {
                $.formValidator.appendValid(this.id, settings);
            });
        };

        $.fn.ajaxValidator = function (controlOptions) {
            var settings = {
                isvalid: false,
                lastValid: "",
                type: "GET",
                url: "",
                addidvalue: true,
                datatype: "html",
                data: "",
                async: true,
                cache: false,
                beforesend: function () {
                    return true;
                },
                success: function () {
                    return true;
                },
                complete: function () {
                },
                processdata: true,
                error: function () {
                },
                buttons: null,
                onerror: "服务器校验没有通过",
                onwait: "正在等待服务器返回数据",
                validatetype: "AjaxValidator"
            };
            controlOptions = controlOptions || {};
            $.extend(true, settings, controlOptions);
            return this.each(function () {
                $.formValidator.appendValid(this.id, settings);
            });
        };

        $.fn.defaultPassed = function (onshow) {
            return this.each(function () {
                var settings = this.settings;
                for (var i = 1; i < settings.length; i++) {
                    settings[i].isvalid = true;
                    if (!$.formValidator
                        .getInitConfig(settings[0].validatorgroup).alertmessage) {
                        var ls_style = window.globalSuccessClass;
                        if (onshow) {
                            ls_style = "onShow";
                        }
                        ;
                        $.formValidator.setTipState(settings[0].tipid,
                            ls_style, settings[0].oncorrect);
                    }
                }
            });
        };

        $.fn.unFormValidator = function (unbind) {
            return this.each(function () {
                this.settings[0].bind = !unbind;
                if (unbind) {
                    $("#" + this.settings[0].tipid).hide();
                } else {
                    $("#" + this.settings[0].tipid).show();
                }
            });
        };

    })(jQuery);
});